﻿using Tetris.Game.ControlsBase;

namespace Tetris.Game.Common.TetrisCenter
{
    public unsafe static class TetrisGameEx
    {
        public static Point GetRotatePoint(this RotationAngle angle, int x, int y, int centerX, int centerY)
        {
            double radianDegrees = angle.GetRadianDegrees();
            int newX, newY;
            // newX=(x-a)cosθ-(y-b)sinθ+a
            newX = (int)Math.Round((x - centerX) * Math.Cos(radianDegrees) - (y - centerY) * Math.Sin(radianDegrees) + centerX, 0);
            // newY=(x-a)sinθ-(y-b)cosθ+b
            newY = (int)Math.Round((x - centerX) * Math.Sin(radianDegrees) - (y - centerY) * Math.Cos(radianDegrees) + centerY, 0);
            return new Point(newX, newY);
        }

        /// <summary>
        /// 获取行变换数
        /// 行变换数。按行遍历，从哪一行有方块开始计算，边界定义为没有方块，从方块到空记作一次变换，从空到有方块在记作一次变化
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardRowTransitions(BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int i, j, transitions = 0, curRow;
            bool lastCellWasBlock, currentCellIsBlock;
            fixed (BlockControl* blocks = grid)
            {
                for (i = 0; i < rows; i++)
                {
                    lastCellWasBlock = false;
                    curRow = i * cols;
                    for (j = 0; j < cols; j++)
                    {
                        currentCellIsBlock = (*(blocks + curRow + j)) != null;
                        // 检查是否有从最后一个单元格到当前单元格的转换
                        if (lastCellWasBlock != currentCellIsBlock)
                        {
                            transitions++;
                        }
                        lastCellWasBlock = currentCellIsBlock;
                    }
                }
            }

            return transitions;
        }
        /// <summary>
        /// 获取列变换数
        /// 列变换数：同行变换数，只不过换成了按列遍历。
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardColTransitions(BlockControl[,] grid)
        {
            int rows = grid.GetLength(0);
            int cols = grid.GetLength(1);
            int i, j, transitions = 0;
            for (j = 0; j < cols; j++)
            {
                bool lastCellWasBlock = true;

                for (i = 0; i < rows; i++)
                {
                    bool currentCellIsBlock = grid[i, j] != null;

                    // 检查是否有从最后一个单元格到当前单元格的转换
                    if (lastCellWasBlock != currentCellIsBlock)
                    {
                        transitions++;
                    }

                    lastCellWasBlock = currentCellIsBlock;
                }
            }

            return transitions;
        }
        /// <summary>
        /// 获取空洞数
        /// 解释：
        ///     空洞数，空洞指的是，每列中某个方块下面没有方块的空白位置，该空白可能由 1 个单位或多个单位组成，但只要没有被方块隔断，
        ///     都只算一个空洞。注意，空洞的计算以列为单位，若不同列的相邻空格连在一起，不可以将它们算作同一个空洞。
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardBuriedHoles(BlockControl[,] grid)
        {
            int rows = grid.GetLength(0) - 1;
            int cols = grid.GetLength(1);
            int i, j, holes = 0;
            fixed (BlockControl* blocks = grid)
            {
                for (j = 0; j < cols; j++)
                {
                    bool isHole = false;
                    for (i = rows; i >= 0; i--)
                    {
                        bool isBlock = (*(blocks + i * cols + j)) != null;
                        if (isBlock && isHole)
                        {
                            holes++;
                        }
                        isHole = !isBlock;
                    }
                }
            }

            return holes;
        }
        /// <summary>
        /// 获取井数
        /// 解释：
        ///     井数，与字面意义一样–水井一样的个数。井指的是某一列中，两边都有方块的连续空格，（左右两侧看成一个环，不算做边界）。
        ///     还需要注意井深度，井的深度是连续累加的，例如：若一个井由 1 个方块组成，则为 1 ；若由连续 3 个组成，则和为 1 + 2 + 3 
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public unsafe static int GetBoardWells(BlockControl[,] grid)
        {
            int rows = grid.GetLength(0) - 1;
            int cols = grid.GetLength(1);
            int i, j, wells = 0, currentWellDepth;
            fixed (BlockControl* blocks = grid)
            {
                int curRow;
                for (j = 0; j < cols; j++)
                {
                    currentWellDepth = 0;
                    for (i = rows; i >= 0; i--)
                    {
                        BlockControl* temp = blocks + i * cols;
                        // 检查当前单元格是否是一个洞并且被块包围
                        if ((*(temp + j)) == null &&
                            (*(temp + (j - 1 + cols) % cols)) != null &&
                            (*(temp + (j + 1) % cols)) != null)
                        {
                            // 增加当前井深并将其添加到井深总和中
                            currentWellDepth++;
                            wells += currentWellDepth;
                        }
                        else
                            currentWellDepth = 0;
                    }
                }
            }

            return wells;
        }
    }
}
